import axios from 'axios'
import type { AxiosInstance, InternalAxiosRequestConfig, AxiosResponse, AxiosRequestConfig } from 'axios'
import { ElMessage, ElLoading } from 'element-plus'
import type { ApiResponse } from '@/types/common'
import router from '@/router'

// 全局 loading 状态
let loadingInstance: ReturnType<typeof ElLoading.service> | null = null

// 创建axios实例
const service: AxiosInstance = axios.create({
  baseURL: '/api',
  timeout: 15000,
  headers: {
    'Content-Type': 'application/json;charset=UTF-8'
  }
})

// 不需要认证的公开接口
const publicUrls = [
  '/auth/login',
  '/auth/web-login', 
  '/auth/register',
  '/auth/refresh-token',
  '/tutorial/list',
  '/tutorial/recommend',
  '/tutorial/free',
  '/tutorial/search',
  '/tutorial/category-stats',
  '/tutorial-step',  // 添加所有教程步骤相关接口
  '/culture/list',
  '/culture/recommend', 
  '/culture/search',
  '/culture/category-stats',
  '/news/list',
  '/news/recommend',
  '/news/top',
  '/news/search',
  '/banner/active',
  '/carousel/list',  // 添加轮播图接口
  '/config',
  '/ai/chat',  // AI聊天接口
  '/ai/stream-chat',  // AI流式聊天接口
  '/ai/clear-history'  // AI清除历史接口
]

// 需要特殊处理的详情接口（只有GET请求是公开的）
const detailUrls = [
  '/tutorial/',  // 教程详情
  '/culture/',   // 文化详情
  '/news/'       // 新闻详情
]

// 检查是否为公开接口
const isPublicUrl = (url: string, method: string = 'GET') => {
  // 检查普通公开接口
  const isPublic = publicUrls.some(publicUrl => {
    // 精确匹配或路径匹配
    return url.includes(publicUrl) || url.match(new RegExp(publicUrl.replace(/\/$/, '') + '(/\\d+)?$'))
  })
  
  if (isPublic) return true
  
  // 检查详情接口（只有GET请求是公开的）
  if (method.toUpperCase() === 'GET') {
    return detailUrls.some(detailUrl => {
      // 匹配详情接口模式：/culture/123, /tutorial/456, /news/789
      return url.match(new RegExp(detailUrl.replace(/\/$/, '') + '\\d+$'))
    })
  }
  
  // 确保交互接口（like、favorite、interaction）不被误认为是公开接口
  const interactionPatterns = [
    '/like$',
    '/favorite$', 
    '/interaction$',
    '/view$'
  ]
  
  const isInteractionUrl = interactionPatterns.some(pattern => 
    url.match(new RegExp(pattern))
  )
  
  if (isInteractionUrl) {
    return false // 交互接口需要认证
  }
  
  return false
}

// 获取token
const getToken = () => {
  return localStorage.getItem('token') || ''
}

// 设置token
const setToken = (token: string) => {
  localStorage.setItem('token', token)
}

// 清除token
const clearToken = () => {
  localStorage.removeItem('token')
  localStorage.removeItem('userInfo')
}

// 请求拦截器
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    const token = getToken()

    // 添加token（排除公开接口）
    if (token && !isPublicUrl(config.url || '', config.method || 'GET')) {
      config.headers = config.headers || {}
      config.headers.Authorization = `Bearer ${token}`
    }

    // 显示加载提示
    if ((config as any).loading !== false) {
      loadingInstance = ElLoading.service({
        text: '加载中...',
        background: 'rgba(0, 0, 0, 0.7)',
      })
    }

    return config
  },
  (error) => {
    if (loadingInstance) {
      loadingInstance.close()
      loadingInstance = null
    }
    console.error('请求错误:', error)
    return Promise.reject(error)
  }
)

// 响应拦截器
service.interceptors.response.use(
  (response: AxiosResponse<ApiResponse>) => {
    if (loadingInstance) {
      loadingInstance.close()
      loadingInstance = null
    }
    
    const { code, message, data } = response.data
    
    // 成功响应
    if (code === 200) {
      return response.data as any
    }
    
    // 未授权，跳转登录
    if (code === 401) {
      clearToken()
      router.push('/login')
      ElMessage.error('登录已过期，请重新登录')
      return Promise.reject(new Error(message))
    }
    
    // 其他错误
    ElMessage.error(message || '请求失败')
    return Promise.reject(new Error(message))
  },
  (error) => {
    if (loadingInstance) {
      loadingInstance.close()
      loadingInstance = null
    }
    
    let message = '网络错误'
    
    if (error.response) {
      const { status, data } = error.response
      
      switch (status) {
        case 400:
          message = data?.message || '请求参数错误'
          break
        case 401:
          message = '未授权，请登录'
          clearToken()
          router.push('/login')
          break
        case 403:
          message = '拒绝访问'
          break
        case 404:
          message = '请求地址不存在'
          break
        case 500:
          message = '服务器内部错误'
          break
        default:
          message = data?.message || `连接错误${status}`
      }
    } else if (error.code === 'ECONNABORTED') {
      message = '请求超时'
    } else if (error.message.includes('Network Error')) {
      message = '网络连接异常'
    }
    
    ElMessage.error(message)
    console.error('请求错误:', error)
    return Promise.reject(error)
  }
)

// 请求方法封装
export const request = {
  get<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<ApiResponse<T>> {
    return service.get(url, config)
  },
  
  post<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<ApiResponse<T>> {
    return service.post(url, data, config)
  },
  
  put<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<ApiResponse<T>> {
    return service.put(url, data, config)
  },
  
  delete<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<ApiResponse<T>> {
    return service.delete(url, config)
  },
  
  upload<T = unknown>(url: string, formData: FormData, config?: AxiosRequestConfig): Promise<ApiResponse<T>> {
    return service.post(url, formData, {
      ...config,
      headers: {
        'Content-Type': 'multipart/form-data'
      }
    })
  }
}

// 导出工具函数
export { getToken, setToken, clearToken }

export default service
